/**
 * Copyright (C) 2018-2022
 * All rights reserved, Designed By www.yixiang.co
 * 注意：
 * 本软件为www.yixiang.co开发研制
 */
package co.yixiang.modules.order.order.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.cache.Cache;
import co.yixiang.common.enums.ResultCode;
import co.yixiang.common.exception.BadRequestException;
import co.yixiang.common.exception.EntityExistException;
import co.yixiang.common.exception.ServiceException;
import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.common.utils.*;
import co.yixiang.dozer.service.IGenerator;
import co.yixiang.modules.activity.entity.domain.YxStorePink;
import co.yixiang.modules.activity.service.YxStorePinkService;
import co.yixiang.modules.adopt.entity.domain.YxAdoptProduct;
import co.yixiang.modules.adopt.service.YxAdoptProductService;
import co.yixiang.modules.goods.entity.domain.YxStoreProduct;
import co.yixiang.modules.goods.mapper.StoreProductMapper;
import co.yixiang.modules.goods.service.YxStoreProductService;
import co.yixiang.modules.member.entity.domain.YxUser;
import co.yixiang.modules.member.entity.domain.YxUserBill;
import co.yixiang.modules.member.entity.domain.YxUserIntegralDetail;
import co.yixiang.modules.member.entity.dto.YxUserDto;
import co.yixiang.modules.member.mapper.UserMapper;
import co.yixiang.modules.member.service.YxUserBillService;
import co.yixiang.modules.member.service.YxUserIntegralDetailService;
import co.yixiang.modules.member.service.YxUserService;
import co.yixiang.modules.mp.service.YxMiniPayService;
import co.yixiang.modules.mp.service.YxPayService;
import co.yixiang.modules.order.cart.entity.dto.TradeDTO;
import co.yixiang.modules.order.cart.entity.enums.DeliveryMethodEnum;
import co.yixiang.modules.order.order.entity.domain.OrderItem;
import co.yixiang.modules.order.order.entity.domain.YxStoreCart;
import co.yixiang.modules.order.order.entity.domain.YxStoreOrder;
import co.yixiang.modules.order.order.entity.domain.YxStoreOrderStatus;
import co.yixiang.modules.order.order.entity.dto.*;
import co.yixiang.modules.order.order.entity.enums.*;
import co.yixiang.modules.order.order.entity.vo.OrderItemVO;
import co.yixiang.modules.order.order.entity.vo.StoreOrderDetailVO;
import co.yixiang.modules.order.order.entity.vo.YxStoreOrderVo;
import co.yixiang.modules.order.order.entity.vo.YxStoreOrderVoF;
import co.yixiang.modules.order.order.mapper.StoreOrderMapper;
import co.yixiang.modules.order.order.service.OrderItemService;
import co.yixiang.modules.order.order.service.YxStoreCartService;
import co.yixiang.modules.order.order.service.YxStoreOrderService;
import co.yixiang.modules.order.order.service.YxStoreOrderStatusService;
import co.yixiang.modules.order.trade.entity.dos.OrderLog;
import co.yixiang.modules.order.trade.entity.enums.AfterSaleStatusEnum;
import co.yixiang.modules.order.trade.entity.vo.OrderLogVo;
import co.yixiang.modules.order.trade.service.OrderLogService;
import co.yixiang.modules.payment.entity.RefundLog;
import co.yixiang.modules.payment.entity.enums.PaymentMethodEnum;
import co.yixiang.modules.payment.kit.Payment;
import co.yixiang.modules.security.entity.vo.AuthUser;
import co.yixiang.modules.security.enums.UserEnums;
import co.yixiang.modules.shop.entity.domain.YxSystemStore;
import co.yixiang.modules.shop.entity.dto.CountDto;
import co.yixiang.modules.shop.service.YxSystemStoreService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;

/**
 * @author hupeng
 * @date 2020-05-12
 */
@Slf4j
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class YxStoreOrderServiceImpl extends BaseServiceImpl<StoreOrderMapper, YxStoreOrder> implements YxStoreOrderService {
    @Autowired
    private IGenerator generator;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private  StoreOrderMapper yxStoreOrderMapper;
    @Autowired
    private StoreProductMapper yxStoreProductMapper;
    @Autowired
    private YxUserService userService;
    @Autowired
    private YxStorePinkService storePinkService;
    @Autowired
    private  YxUserBillService yxUserBillService;
    @Autowired
    private YxStoreOrderStatusService yxStoreOrderStatusService;
    @Autowired
    private  YxPayService payService;
    @Autowired
    private  YxMiniPayService miniPayService;
    @Autowired
    private  YxSystemStoreService systemStoreService;
    @Autowired
    private YxStoreCartService storeCartService;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private YxStoreProductService productService;
    @Autowired
    private YxAdoptProductService adoptProductService;
    @Autowired
    private YxUserIntegralDetailService integralDetailService;

//
//    /**
//     * Redis
//     */
//    @Autowired
//    private StringRedisTemplate stringRedisTemplate;
//    @Autowired
//    private DefaultRedisScript<Boolean> quantityScript;
    /**
     * 缓存
     */
    @Autowired
    private Cache cache;
    /**
     * 订单日志
     */
    @Autowired
    private OrderLogService orderLogService;

    @Override
    public OrderCountDto getOrderCount() {
        //获取所有订单状态为已支付的
        List<CountDto> nameList = storeCartService.findCateName();
        Map<String, Integer> childrenMap = new HashMap<>();
        nameList.forEach(i -> {
            if (i != null) {
                if (childrenMap.containsKey(i.getCatename())) {
                    childrenMap.put(i.getCatename(), childrenMap.get(i.getCatename()) + 1);
                } else {
                    childrenMap.put(i.getCatename(), 1);
                }
            }
        });
        List<OrderCountDto.OrderCountData> list = new ArrayList<>();
        List<String> columns = new ArrayList<>();
        childrenMap.forEach((k, v) -> {
            OrderCountDto.OrderCountData orderCountData = new OrderCountDto.OrderCountData();
            orderCountData.setName(k);
            orderCountData.setValue(v);
            columns.add(k);
            list.add(orderCountData);
        });
        OrderCountDto orderCountDto = new OrderCountDto();
        orderCountDto.setColumn(columns);
        orderCountDto.setOrderCountDatas(list);
        return orderCountDto;
    }

    @Override
    // 此处方法已经废弃
    public OrderTimeDataDto getOrderTimeData() {
        int today = OrderUtil.dateToTimestampT(DateUtil.beginOfDay(new Date()));
        int yesterday = OrderUtil.dateToTimestampT(DateUtil.beginOfDay(DateUtil.
                yesterday()));
        int lastWeek = OrderUtil.dateToTimestampT(DateUtil.beginOfDay(DateUtil.lastWeek()));
        int nowMonth = OrderUtil.dateToTimestampT(DateUtil
                .beginOfMonth(new Date()));
        OrderTimeDataDto orderTimeDataDTO = new OrderTimeDataDto();

        orderTimeDataDTO.setTodayCount(yxStoreOrderMapper.countByPayTimeGreaterThanEqual(today));


        orderTimeDataDTO.setProCount(yxStoreOrderMapper
                .countByPayTimeLessThanAndPayTimeGreaterThanEqual(today, yesterday));


        orderTimeDataDTO.setLastWeekCount(yxStoreOrderMapper.countByPayTimeGreaterThanEqual(lastWeek));


        orderTimeDataDTO.setMonthCount(yxStoreOrderMapper.countByPayTimeGreaterThanEqual(nowMonth));


        orderTimeDataDTO.setUserCount(userMapper.selectCount(new LambdaQueryWrapper<YxUser>()));
        orderTimeDataDTO.setOrderCount(yxStoreOrderMapper.selectCount(new LambdaQueryWrapper<YxStoreOrder>()));
        orderTimeDataDTO.setPriceCount(yxStoreOrderMapper.sumTotalPrice());
        orderTimeDataDTO.setGoodsCount(yxStoreProductMapper.selectCount(new LambdaQueryWrapper<YxStoreProduct>()));
        return orderTimeDataDTO;
    }

    @Override
    public Map<String, Object> chartCount() {
        Map<String, Object> map = new LinkedHashMap<>();
        int nowMonth = OrderUtil.dateToTimestampT(DateUtil.beginOfMonth(new Date()));
        map.put("chart", yxStoreOrderMapper.chartList(nowMonth));
        map.put("chartT", yxStoreOrderMapper.chartListT(nowMonth));
        return map;
    }


    @Override
    public Map<String, Object> queryAllToVo(YxStoreOrderQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        QueryWrapper<YxStoreOrder> wrapper = new QueryWrapper<YxStoreOrder>();
        final AuthUser authUser = SecurityUtils.getAuthUser();
        wrapper.eq("uid", authUser.getUuid());
        wrapper.eq("order_type", criteria.getOrderType());
        //订单状态查询
        if (StrUtil.isNotEmpty(criteria.getOrderStatus())) {
            List<String> s1 = new ArrayList<String>(){{
                add(OrderStatusEnum.PAID.name());
                add(OrderStatusEnum.UNDELIVERED.name());
                add(OrderStatusEnum.DELIVERED.name());
                add(OrderStatusEnum.TAKE.name());
            }};
            switch (criteria.getOrderStatus()) {
                case "UNPAID":
                    wrapper.eq("order_status", OrderStatusEnum.UNPAID.name());
                    break;
                case "DELIVERED":
                    wrapper.in("order_status", s1);
                    break;
                case "COMPLETED":
                    wrapper.eq("order_status", OrderStatusEnum.COMPLETED.name());
                    break;
                case "REFUND":
                    wrapper.eq("order_status", OrderStatusEnum.REFUND.name());
                    break;
                case "CANCELLED":
                    wrapper.eq("order_status", OrderStatusEnum.CANCELLED.name());
                    break;
                default:
            }
        }
        PageInfo<YxStoreOrder> page = new PageInfo<>(list(wrapper));
        List<YxStoreOrderVoF> storeOrderVoList = new ArrayList<>();
        // 数据处理
        for (YxStoreOrder yxStoreOrder : page.getList()) {
            YxStoreOrderVoF yxStoreOrderVo = generator.convert(yxStoreOrder, YxStoreOrderVoF.class);
            // 子订单，包含商品信息
            List<OrderItem> orderInfos = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn, yxStoreOrder.getSn()));
            List<OrderItemVO> itemVOList = generator.convert(orderInfos, OrderItemVO.class);
            yxStoreOrderVo.setOrderItemList(itemVOList);
            storeOrderVoList.add(yxStoreOrderVo);
        }
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", storeOrderVoList);
        map.put("totalElements", page.getTotal());
        return map;
    }

    @Override
    public YxStoreOrderVoF queryOrderDetail(String sn) {
       YxStoreOrder order = getBySn(sn);
       YxStoreOrderVoF yxStoreOrderVoF = orderToVo(order);
       return yxStoreOrderVoF;
    }

    @Override
    public Map<String, Integer> orderStatusSizeBYUid() {
        final AuthUser authUser = SecurityUtils.getAuthUser();
        List<Map<String, Object>> maps = this.baseMapper.selectOrderStatusSizeByUid(authUser.getUuid());
        Map<String, Integer> result = new HashMap<>();

        //
        Integer unpaid = 0;
        // 已发货
        Integer delivered = 0;
        // 售后
        Integer completed = 0;
        Integer refund = 0;
        Integer cancelled = 0;
        for (Map<String, Object> v : maps) {
            if (v.get("order_status").toString().equals(OrderStatusEnum.UNPAID.name())) {
                unpaid = Integer.parseInt(v.get("size").toString());
            }
            if (v.get("order_status").toString().equals(OrderStatusEnum.PAID.name())) {
                delivered = Integer.parseInt(v.get("size").toString());
            }
            if (v.get("order_status").toString().equals(OrderStatusEnum.UNDELIVERED.name())) {
                delivered = Integer.parseInt(v.get("size").toString());
            }
            if (v.get("order_status").toString().equals(OrderStatusEnum.DELIVERED.name())) {
                delivered = Integer.parseInt(v.get("size").toString());
            }
            if (v.get("order_status").toString().equals(OrderStatusEnum.TAKE.name())) {
                delivered = Integer.parseInt(v.get("size").toString());
            }
            if (v.get("order_status").toString().equals(OrderStatusEnum.COMPLETED.name())) {
                completed = Integer.parseInt(v.get("size").toString());
            }
            if (v.get("order_status").toString().equals(OrderStatusEnum.REFUND.name())) {
                refund = Integer.parseInt(v.get("size").toString());
            }
            if (v.get("order_status").toString().equals(OrderStatusEnum.CANCELLED.name())) {
                cancelled = Integer.parseInt(v.get("size").toString());
            }
        };
        result.put(OrderStatusEnum.UNPAID.name(), unpaid);
        result.put(OrderStatusEnum.DELIVERED.name(), delivered);
        result.put(OrderStatusEnum.COMPLETED.name(), completed);
        result.put(OrderStatusEnum.REFUND.name(), refund);
        result.put(OrderStatusEnum.CANCELLED.name(), cancelled);
        result.put("TOTAL", unpaid+delivered+completed+refund+cancelled);
        return result;
    }

    @Override
    //@Cacheable
    public Map<String, Object> queryAll(YxStoreOrderQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        PageInfo<YxStoreOrder> page = new PageInfo<>(queryAll(criteria));
        List<YxStoreOrderDto> storeOrderDTOS = new ArrayList<>();
        for (YxStoreOrder yxStoreOrder : page.getList()) {
            orderList(storeOrderDTOS, yxStoreOrder);
        }
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", storeOrderDTOS);
        map.put("totalElements", page.getTotal());
        return map;
    }

    /**
     * 代码提取
     * @param yxStoreOrder
     * @return YxStoreOrderVoF
     */
    private YxStoreOrderVoF orderToVo(YxStoreOrder yxStoreOrder) {
        YxStoreOrderVoF yxStoreOrderVo = generator.convert(yxStoreOrder, YxStoreOrderVoF.class);
        // 店铺信息
        if (yxStoreOrder.getStoreId() > 0) {
            YxSystemStore systemStore = systemStoreService.getById(yxStoreOrder.getStoreId());
            if (Objects.nonNull(systemStore)) {
                String storeName = systemStore.getName();
                yxStoreOrderVo.setStoreName(storeName);
            }
        }
        yxStoreOrderVo.setPinkName(orderType(yxStoreOrder.getId(), yxStoreOrder.getPinkId(), yxStoreOrder.getCombinationId(), yxStoreOrder.getSeckillId(), yxStoreOrder.getBargainId(), yxStoreOrder.getDeliveryMethod(),yxStoreOrder.getOrderType()));
        // 设置用户信息
        yxStoreOrderVo.setUserDTO(generator.convert(userService.getById(yxStoreOrder.getUid()), YxUserDto.class));
        if (ObjectUtil.isEmpty(yxStoreOrderVo.getUserDTO())) {
            yxStoreOrderVo.setUserDTO(new YxUserDto());
        }
        // 子订单，包含商品信息
        List<OrderItem> orderInfos = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn, yxStoreOrder.getSn()));
        List<OrderItemVO> itemVOList = generator.convert(orderInfos, OrderItemVO.class);
        yxStoreOrderVo.setOrderItemList(itemVOList);
        // orderLog信息
        List<OrderLog> orderLogList = orderLogService.list(new LambdaQueryWrapper<OrderLog>().eq(OrderLog::getOrderSn, yxStoreOrder.getSn()));
        final List<OrderLogVo> orderLogVoList = generator.convert(orderLogList, OrderLogVo.class);
        yxStoreOrderVo.setOrderLogVoList(orderLogVoList);
        // 保存到集合中
        return yxStoreOrderVo;
    }

    /**
     * 代码提取
     * @param storeOrderDTOS
     * @param yxStoreOrder
     */
    private void orderList(List<YxStoreOrderDto> storeOrderDTOS, YxStoreOrder yxStoreOrder) {
        YxStoreOrderDto yxStoreOrderDto = generator.convert(yxStoreOrder, YxStoreOrderDto.class);
        // 店铺信息
        if (yxStoreOrder.getStoreId() > 0) {
            YxSystemStore systemStore = systemStoreService.getById(yxStoreOrder.getStoreId());
            if (Objects.nonNull(systemStore)) {
                String storeName = systemStore.getName();
                yxStoreOrderDto.setStoreName(storeName);
            }
        }
        //订单状态
       String orderStatusStr = OrderUtil.orderStatusStr(yxStoreOrder.getOrderStatus(),yxStoreOrder.getDeliveryMethod(), yxStoreOrder.getDeliverStatus(), yxStoreOrder.getRefundStatus());
        if (yxStoreOrder.getOrderStatus().equals(OrderStatusEnum.REFUND.name())) {
            String refundTime = DateUtil.formatTime(new Date());
            if (ObjectUtil.isNotEmpty(yxStoreOrder.getRefundReasonTime())) {
                refundTime = DateUtil.formatTime(yxStoreOrder.getRefundReasonTime()) ;
            }

            String str = "<b style='color:#f124c7'>申请退款</b><br/>" +
                    "<span>退款原因：" + yxStoreOrder.getRefundReasonWap() + "</span><br/>" +
                    "<span>备注说明：" + yxStoreOrder.getRefundReasonWapExplain() + "</span><br/>" +
                    "<span>退款时间：" + refundTime + "</span><br/>";
            orderStatusStr = str;
        }
        yxStoreOrderDto.setStatusName(orderStatusStr);
        String payTypeName = OrderUtil.payTypeName(yxStoreOrder.getPaymentMethod(), yxStoreOrder.getPayStatus());
        yxStoreOrderDto.setPayTypeName(payTypeName);
        yxStoreOrderDto.setPinkName(orderType(yxStoreOrder.getId(), yxStoreOrder.getPinkId(), yxStoreOrder.getCombinationId(), yxStoreOrder.getSeckillId(), yxStoreOrder.getBargainId(), yxStoreOrder.getDeliveryMethod(),yxStoreOrder.getOrderType()));
        // 子订单，包含商品信息
        List<OrderItem> orderInfos = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn, yxStoreOrder.getSn()));
        List<OrderItemVO> orderInfoVOs = new ArrayList<>();
        for (OrderItem orderItem : orderInfos) {
            OrderItemVO orderItemVO = BeanUtil.copyProperties(orderItem, OrderItemVO.class);
            orderInfoVOs.add(orderItemVO);
        }
        yxStoreOrderDto.setOrderItemList(orderInfoVOs);
        // 设置用户信息
        yxStoreOrderDto.setUserDTO(generator.convert(userService.getById(yxStoreOrder.getUid()), YxUserDto.class));
        if (ObjectUtil.isEmpty(yxStoreOrderDto.getUserDTO())) {
            yxStoreOrderDto.setUserDTO(new YxUserDto());
        }
        storeOrderDTOS.add(yxStoreOrderDto);
    }


    @Override
    //@Cacheable
    public List<YxStoreOrder> queryAll(YxStoreOrderQueryCriteria criteria) {
        return baseMapper.selectList(QueryHelpPlus.getPredicate(YxStoreOrder.class, criteria));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YxStoreOrderDto create(YxStoreOrder resources) {
        if (this.getOne(new LambdaQueryWrapper<YxStoreOrder>().eq(YxStoreOrder::getUnique, resources.getUnique())) != null) {
            throw new EntityExistException(YxStoreOrder.class, "unique", resources.getUnique());
        }
        this.save(resources);
        return generator.convert(resources, YxStoreOrderDto.class);
    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(YxStoreOrder resources) {
        YxStoreOrder yxStoreOrder = this.getById(resources.getId());
        YxStoreOrder yxStoreOrder1 = this.getOne(new LambdaQueryWrapper<YxStoreOrder>().eq(YxStoreOrder::getUnique, resources.getUnique()));
        if (yxStoreOrder1 != null && !yxStoreOrder1.getId().equals(yxStoreOrder.getId())) {
            throw new EntityExistException(YxStoreOrder.class, "unique", resources.getUnique());
        }
        yxStoreOrder.copy(resources);
        this.saveOrUpdate(yxStoreOrder);
    }

    @Override
    public void deliverGoods(StoreOrderExpress order) {
        final YxStoreOrder bySn = this.getBySn(order.getSn());
        bySn.setOrderStatus(OrderStatusEnum.DELIVERED.name());
        bySn.setDeliverStatus(DeliverStatusEnum.DELIVERED.name());
        bySn.setLogisticsNo(order.getLogisticsNo());
        bySn.setLogisticsCode(order.getLogisticsCode());
        bySn.setLogisticsName(order.getLogisticsName());
        bySn.setLogisticsTime(new Date());
        this.updateById(bySn);
        String message = "订单[" + order.getSn() + "]发货";
        //记录日志
        final UserDetails userDetails = SecurityUtils.getUserDetails();
        orderLogService.save(  new OrderLog(order.getSn(), "-1","ADMIN",  userDetails.getUsername(), message));
    }


    @Override
    public void download(List<YxStoreOrderDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (YxStoreOrderDto yxStoreOrder : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("订单号", yxStoreOrder.getSn());
            map.put("用户id", yxStoreOrder.getUid());
            map.put("用户姓名", yxStoreOrder.getRealName());
            map.put("购物车id", yxStoreOrder.getCartId());
            map.put("运费金额", yxStoreOrder.getFreightPrice());
            map.put("订单商品总数", yxStoreOrder.getTotalNum());
            map.put("订单总价", yxStoreOrder.getTotalPrice());
            map.put("实际支付金额", yxStoreOrder.getPayPrice());
            map.put("抵扣金额", yxStoreOrder.getDiscountPrice());
            map.put("优惠券id", yxStoreOrder.getCouponId());
            map.put("优惠券金额", yxStoreOrder.getCouponPrice());
            map.put("支付状态", yxStoreOrder.getPayStatus());
            map.put("支付时间", yxStoreOrder.getPaymentTime());
            map.put("支付方式", yxStoreOrder.getPaymentMethod());
            map.put("订单状态（-1 : 申请退款 -2 : 退货成功 0：待发货；1：待收货；2：已收货；3：待评价；-1：已退款）", yxStoreOrder.getStatus());
            map.put("0 未退款 1 申请中 2 已退款", yxStoreOrder.getRefundStatus());
            map.put("退款图片", yxStoreOrder.getRefundReasonWapImg());
            map.put("退款用户说明", yxStoreOrder.getRefundReasonWapExplain());
            map.put("退款时间", yxStoreOrder.getRefundReasonTime());
            map.put("前台退款原因", yxStoreOrder.getRefundReasonWap());
            map.put("不退款的理由", yxStoreOrder.getRefundReason());
            map.put("退款金额", yxStoreOrder.getRefundPrice());
            map.put("快递公司编号", yxStoreOrder.getLogisticsCode());
            map.put("快递名称/送货人姓名", yxStoreOrder.getLogisticsName());
            map.put("发货类型", yxStoreOrder.getDeliveryType());
            map.put("快递单号/手机号", yxStoreOrder.getLogisticsNo());
            map.put("消费赚取积分", yxStoreOrder.getGainIntegral());
            map.put("使用积分", yxStoreOrder.getUseIntegral());
            map.put("给用户退了多少积分", yxStoreOrder.getBackIntegral());
            map.put("备注", yxStoreOrder.getMark());
            map.put("管理员备注", yxStoreOrder.getRemark());
            map.put("拼团产品id0一般产品", yxStoreOrder.getCombinationId());
            map.put("拼团id 0没有拼团", yxStoreOrder.getPinkId());
            // map.put("成本价", yxStoreOrder.getCost());
            map.put("秒杀产品ID", yxStoreOrder.getSeckillId());
            map.put("砍价id", yxStoreOrder.getBargainId());
            map.put("核销码", yxStoreOrder.getVerifyCode());
            map.put("门店id", yxStoreOrder.getStoreId());
            map.put("配送方式 1=快递 ，2=门店自提", yxStoreOrder.getShippingType());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Map<String, Object> queryAll(List<String> ids) {
        List<YxStoreOrder> yxStoreOrders = this.list(new LambdaQueryWrapper<YxStoreOrder>().in(YxStoreOrder::getSn, ids));
        List<YxStoreOrderDto> storeOrderDTOS = new ArrayList<>();
        for (YxStoreOrder yxStoreOrder : yxStoreOrders) {
           orderList(storeOrderDTOS, yxStoreOrder);
        }
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", storeOrderDTOS);
        return map;
    }

    @Override
    public String orderType(Long id, Long pinkId, Long combinationId, Long seckillId,
                            Long bargainId, String deliveryMethod, String orderType) {
        String str = "[普通订单]";
        if ( pinkId > 0 || combinationId > 0) {
            YxStorePink storePink = storePinkService.getOne(new LambdaQueryWrapper<YxStorePink>().
                    eq(YxStorePink::getOrderIdKey, id));
            if (ObjectUtil.isNull(storePink)) {
                str = "[拼团订单]";
            } else {
                switch (storePink.getStatus()) {
                    case 1:
                        str = "[拼团订单]正在进行中";
                        break;
                    case 2:
                        str = "[拼团订单]已完成";
                        break;
                    case 3:
                        str = "[拼团订单]未完成";
                        break;
                    default:
                        str = "[拼团订单]历史订单";
                        break;
                }
            }
        } else if (seckillId > 0) {
            str = "[秒杀订单]";
        } else if (bargainId > 0) {
            str = "[砍价订单]";
        }
        if (deliveryMethod.equals(DeliveryMethodEnum.SELF_PICK_UP.name())) {
            str = "[核销订单]";
        }
        if (orderType.equals(OrderTypeEnum.ADOPT.name())) {
            str = "[认养订单]";
        }
        return str;
    }

    @Override
    public void refund(YxStoreOrder resources) {
        if (resources.getPayPrice().doubleValue() < 0) {
            throw new BadRequestException("请输入退款金额");
        }
        if ("yue".equals(resources.getPaymentMethod())) {
            //修改状态
            //resources.setRefundStatus(2);
            resources.setRefundPrice(resources.getPayPrice());
            this.updateById(resources);

            //退款到余额
            YxUserDto userDTO = generator.convert(userService.getOne(new LambdaQueryWrapper<YxUser>().eq(YxUser::getUid, resources.getUid())), YxUserDto.class);
            userMapper.updateMoney(resources.getPayPrice().doubleValue(), resources.getUid());

            YxUserBill userBill = new YxUserBill();
            userBill.setUid(resources.getUid());

            userBill.setLinkId(resources.getId().toString());
            userBill.setPm(1);
            userBill.setTitle("商品退款");
            userBill.setCategory("now_money");
            userBill.setType("pay_product_refund");
            userBill.setNumber(resources.getPayPrice());
            userBill.setBalance(NumberUtil.add(resources.getPayPrice(), userDTO.getNowMoney()));
            userBill.setMark("订单退款到余额");
            userBill.setStatus(1);
            yxUserBillService.save(userBill);


            YxStoreOrderStatus storeOrderStatus = new YxStoreOrderStatus();
            storeOrderStatus.setOid(resources.getId());
            storeOrderStatus.setChangeType("refund_price");
            storeOrderStatus.setChangeMessage("退款给用户：" + resources.getPayPrice() + "元");
            storeOrderStatus.setChangeTime(new Date());

            yxStoreOrderStatusService.save(storeOrderStatus);
        } else {
            BigDecimal bigDecimal = new BigDecimal("100");
            try {
                payService.refundOrder(resources.getSn(),
                        bigDecimal.multiply(resources.getPayPrice()).intValue());

            } catch (WxPayException e) {
                log.info("refund-error:{}", e.getMessage());
                throw new BadRequestException("退款失败:" + e.getMessage());
            }

        }
    }

    /**
     * 获取订单
     *
     * @param orderSn 订单编号
     * @return 订单详情
     */
    @Override
    public YxStoreOrder getBySn(String orderSn) {
        final YxStoreOrder order = this.getOne(new LambdaQueryWrapper<YxStoreOrder>().eq(YxStoreOrder::getSn, orderSn));
        if (ObjectUtil.isEmpty(order)) {
            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
        }
        return order;
    }
    @Override
    public void intoDB(TradeDTO tradeDTO) {
        //检查TradeDTO信息
        // checkTradeDTO(tradeDTO);
        //存放购物车，即业务中的订单
        List<YxStoreOrder> orders = new ArrayList<>(tradeDTO.getCartList().size());
        //存放自订单/订单日志
        List<OrderItem> orderItems = new ArrayList<>();
        List<OrderLog> orderLogs = new ArrayList<>();
        //订单集合
        List<YxStoreOrderVo> orderVOS = new ArrayList<>();
        // 商品IP
        List<Long> goodsId = new ArrayList<>();
        // 订单购物车集合
        //循环购物车
        tradeDTO.getCartList().forEach(item -> {
            YxStoreOrder order = new YxStoreOrder(item, tradeDTO);
            //构建orderVO对象
            YxStoreOrderVo orderVO = new YxStoreOrderVo();
            BeanUtil.copyProperties(order, orderVO);
            //持久化DO
            order.setGainIntegral(order.getPayPrice());
            orders.add(order);
            String message = "订单[" + item.getSn() + "]创建";
            //记录日志
            // UserContext.getCurrentUser().getRole().getRole(),
            final AuthUser authUser = SecurityUtils.getAuthUser();
            orderLogs.add(new OrderLog(item.getSn(), authUser.getUuid(),authUser.getRole().name(),  authUser.getRealName(), message));
            item.getCheckedSkuList().forEach(
                    sku -> {
                        orderItems.add(new OrderItem(sku, item, tradeDTO));
                        goodsId.add(sku.getGoodsSku().getId());
                    }
            );
            // 扣库存

            // 写入子订单信息
            orderVO.setOrderItems(orderItems);
            // orderVO 记录
            orderVOS.add(orderVO);
        });
        // 清空对应的购物车
        storeCartService.remove(new LambdaQueryWrapper<YxStoreCart>().eq(YxStoreCart::getUid,tradeDTO.getUid()).in(YxStoreCart::getProductId,goodsId));
        tradeDTO.setOrderVO(orderVOS);
        //批量保存订单
        this.saveBatch(orders);
        //批量保存 子订单
        orderItemService.saveBatch(orderItems);
        //批量记录订单操作日志
        orderLogService.saveBatch(orderLogs);
    }

    @Override
    public void payOrder(String orderSn, String paymentMethod, String receivableNo) {

        YxStoreOrder order = this.getBySn(orderSn);
        //如果订单已支付，就不能再次进行支付
        if (order.getOrderStatus().equals(OrderStatusEnum.PAID.name())) {
            log.error("订单[ {} ]检测到重复付款，请处理", orderSn);
            throw new ServiceException(ResultCode.PAY_DOUBLE_ERROR);
        }

        //修改订单状态
        order.setPaymentTime(new Date());
        order.setPaymentMethod(paymentMethod);
        order.setPaymentTime(new Date());
        order.setPayStatus(PayStatusEnum.PAID.name());
        order.setOrderStatus(OrderStatusEnum.PAID.name());
        order.setReceivableNo(receivableNo);
        order.setCanReturn(!PaymentMethodEnum.BANK_TRANSFER.name().equals(order.getPaymentMethod()));
        this.updateById(order);
        //获取订单详情
        List<OrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn,order.getSn()));
        //更改订单状态为代发货
        normalOrderConfirm(order.getSn());
        // 扣掉库存
        if (order.getOrderType().equals(OrderTypeEnum.NORMAL.name())) {
            List<YxStoreProduct> goods = new ArrayList<>();
            //循环订单
            for (OrderItem orderItem : orderItems) {
                YxStoreProduct goodsSku = productService.getById(orderItem.getSkuId());
                goodsSku.setStock(goodsSku.getStock() - orderItem.getNum());
                goods.add(goodsSku);
                goodsSku.setPosition(null);
                cache.put(YxStoreProductService.getStockCacheKey(orderItem.getSkuId()),goodsSku.getStock());
            }
            log.info("订单支付，库存扣除：{}", goods);
            //批量修改商品库存
            productService.updateBatchById(goods);
        }
        if (order.getOrderType().equals(OrderTypeEnum.ADOPT.name())) {
            List<YxAdoptProduct> goods = new ArrayList<>();
            //循环订单
            for (OrderItem orderItem : orderItems) {
                YxAdoptProduct goodsSku = adoptProductService.getById(orderItem.getSkuId());
                goodsSku.setStock(goodsSku.getStock() - orderItem.getNum());
                goodsSku.setPosition(null);
                goods.add(goodsSku);
                cache.put(YxAdoptProductService.getStockCacheKey(orderItem.getSkuId()), goodsSku.getStock());
            }
            log.info("订单支付，库存扣除：{}", goods);
            //批量修改商品库存
            adoptProductService.updateBatchById(goods);
        }
        System.out.println("输出!");
        final YxUser byId = userService.getById(order.getUid());
        byId.setIntegral(byId.getIntegral().add(order.getGainIntegral()));
        YxUserIntegralDetail integralDetail = new YxUserIntegralDetail();
        String inteMessage = "订单付款:"+ orderSn;
        integralDetail.setUid(order.getUid());
        integralDetail.setTitle(inteMessage);
        integralDetail.setNumber(order.getGainIntegral().intValue());
        integralDetail.setBalance(byId.getIntegral().intValue());
        integralDetailService.save(integralDetail);
        userService.updateById(byId);
        String message = "订单付款，付款方式[" + paymentMethod + "]";
        OrderLog orderLog = new OrderLog(orderSn, "-1", UserEnums.SYSTEM.getRole(), "系统操作", message);
        orderLogService.save(orderLog);
    }

    /**
     * 普通商品订单确认
     * 修改订单状态为待发货
     * 发送订单状态变更消息
     *
     * @param orderSn 订单编号
     */
    public void normalOrderConfirm(String orderSn) {
        //修改订单
        this.update(new LambdaUpdateWrapper<YxStoreOrder>()
                .eq(YxStoreOrder::getSn, orderSn)
                .set(YxStoreOrder::getOrderStatus, OrderStatusEnum.UNDELIVERED.name()));
    }

    @Override
    public List<YxStoreOrder> getByTradeSn(String tradeSn) {
        LambdaQueryWrapper<YxStoreOrder> queryWrapper = new LambdaQueryWrapper<>();
        return this.list(queryWrapper.eq(YxStoreOrder::getTradeSn, tradeSn));
    }

    @Override
    public StoreOrderDetailVO queryDetail(String orderSn) {
        YxStoreOrder order = this.getBySn(orderSn);
        //查询订单项信息
        List<OrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn,order.getSn()));
        //查询订单日志信息
        List<OrderLog> orderLogs = orderLogService.getOrderLog(orderSn);
        //查询订单和自订单，然后写入vo返回
        return new StoreOrderDetailVO(order, orderItems, orderLogs);
    }

    @Override
    public YxStoreOrder cancel(String orderSn, String reason) {
        // TODO 积分
        final AuthUser authUser = SecurityUtils.getAuthUser();
        final YxStoreOrder order = this.getBySn(orderSn);
        if (!order.getUid().equals(authUser.getUuid())) {
            throw new ServiceException(ResultCode.ORDER_NOT_USER);
        }
        if (CharSequenceUtil.equalsAny(order.getOrderStatus(),
                OrderStatusEnum.UNDELIVERED.name(),
                OrderStatusEnum.UNPAID.name(),
                OrderStatusEnum.PAID.name())) {
            order.setOrderStatus(OrderStatusEnum.CANCELLED.name());
            order.setCancelReason(reason);
            //修改订单
            this.updateById(order);
            //获取订单详情
            //StoreOrderDetailVO orderDetail = queryDetail(orderSn);
            //查询订单项信息
            List<OrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn,order.getSn()));
            //判定是否已支付 并且 非库存不足导致库存回滚 则需要考虑订单库存返还业务  && !order.getCancelReason().equals(outOfStockMessage)
            final YxUser byId = userService.getById(authUser.getUuid());
            if (order.getPayStatus().equals(PayStatusEnum.PAID.name())) {
                // TODO, 执行退款操作;

                orderChange(order);
                //执行库存回退
                if (order.getOrderType().equals(OrderTypeEnum.NORMAL.name())) {
                    List<YxStoreProduct> goods = new ArrayList<>();
                    //循环订单
                    for (OrderItem orderItem : orderItems) {
                        YxStoreProduct goodsSku = productService.getById(orderItem.getSkuId());
                        goodsSku.setPosition(null);
                        goodsSku.setStock(goodsSku.getStock() + orderItem.getNum());
                        goods.add(goodsSku);
                        cache.remove(YxStoreProductService.getStockCacheKey(orderItem.getSkuId()));
                    }
                    log.info("订单取消，库存还原：{}", goods);
                    //批量修改商品库存
                    productService.updateBatchById(goods);
                }
                if (order.getOrderType().equals(OrderTypeEnum.ADOPT.name())) {
                    List<YxAdoptProduct> goods = new ArrayList<>();
                    //循环订单
                    for (OrderItem orderItem : orderItems) {
                        YxAdoptProduct goodsSku = adoptProductService.getById(orderItem.getSkuId());
                        goodsSku.setStock(goodsSku.getStock() + orderItem.getNum());
                        goodsSku.setPosition(null);
                        goods.add(goodsSku);
                        cache.remove(YxAdoptProductService.getStockCacheKey(orderItem.getSkuId()));
                    }
                    log.info("订单取消，库存还原：{}", goods);
                    //批量修改商品库存
                    adoptProductService.updateBatchById(goods);
                }

                byId.setIntegral(byId.getIntegral().subtract(order.getGainIntegral()));
                userService.updateById(byId);
            }

            YxUserIntegralDetail integralDetail = new YxUserIntegralDetail();
            String inteMessage = "订单取消:"+ orderSn;
            integralDetail.setUid(authUser.getUuid());
            integralDetail.setTitle(inteMessage);
            integralDetail.setNumber(-order.getGainIntegral().intValue());
            integralDetail.setBalance(byId.getIntegral().intValue());
            integralDetailService.save(integralDetail);
            return order;
        } else {
            throw new ServiceException(ResultCode.ORDER_CAN_NOT_CANCEL);
        }
    }

    @Override
    public YxStoreOrder take(String orderSn) {
        final AuthUser authUser = SecurityUtils.getAuthUser();
        final YxStoreOrder order = this.getBySn(orderSn);
        if (!order.getUid().equals(authUser.getUuid())) {
            throw new ServiceException(ResultCode.ORDER_NOT_USER);
        }
        // 订单状态
        if (!order.getOrderStatus().equals(OrderStatusEnum.DELIVERED.name()) && !order.getDeliverStatus().equals(DeliverStatusEnum.DELIVERED.name())) {
            throw new ServiceException(ResultCode.ORDER_DELIVERED_ERROR);
        }
        order.setOrderStatus(OrderStatusEnum.COMPLETED.name());
        order.setDeliverStatus(DeliverStatusEnum.RECEIVED.name());
        order.setCompleteTime(new Date());
        //修改订单货物可以进行评价
        orderItemService.update(new LambdaUpdateWrapper<OrderItem>().eq(OrderItem::getOrderSn, orderSn).set(OrderItem::getCommentStatus, CommentStatusEnum.UNFINISHED.name()).set(OrderItem::getAfterSaleStatus, OrderItemAfterSaleStatusEnum.NOT_APPLIED.name()));
        // 添加订单日志
        String message = "订单[" + order.getSn() + "]已收货";
        //记录日志
        orderLogService.save(new OrderLog(order.getSn(), authUser.getUuid(),authUser.getRole().name(),  authUser.getRealName(), message));
        // 修改订单状态
        this.updateById(order);
        return order;
    }

    @Override
    public YxStoreOrder afterSale(String orderSn, String reason) {
        final AuthUser authUser = SecurityUtils.getAuthUser();
        final YxStoreOrder order = this.getBySn(orderSn);
        if (!order.getUid().equals(authUser.getUuid())) {
            throw new ServiceException(ResultCode.ORDER_NOT_USER);
        }
        if (order.getOrderStatus().equals(OrderStatusEnum.COMPLETED.name())) {
            order.setRefundReasonWapExplain(reason);
            order.setRefundReasonWap(reason);
            order.setOrderStatus(OrderStatusEnum.REFUND.name());
            //修改订单
            this.updateById(order);
            //查询订单项信息
            List<OrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderSn,order.getSn()));
            orderItems.forEach(orderItem -> {
                orderItem.setAfterSaleStatus(AfterSaleStatusEnum.APPLY.name());
            });
            //修改orderItem订单
            orderItemService.updateBatchById(orderItems);
            return order;
        } else {
            throw new ServiceException(ResultCode.AFTER_SALES_BAN);
        }
    }

    public void orderChange(YxStoreOrder order) {
            //如果未付款，则不去要退回相关代码执行
            if (order.getPayStatus().equals(PayStatusEnum.UNPAID.name())) {
                return;
            }
            PaymentMethodEnum paymentMethodEnum = PaymentMethodEnum.valueOf(order.getPaymentMethod());

            //获取支付方式
            Payment payment = (Payment) SpringContextHolder.getBean(paymentMethodEnum.getPlugin());

            RefundLog refundLog = RefundLog.builder()
                    .isRefund(false)
                    .totalAmount(order.getPayPrice().doubleValue())
                    .payPrice(order.getPayPrice().doubleValue())
                    .uid(order.getUid())
                    .paymentName(order.getPaymentMethod())
                    .afterSaleNo("订单取消")
                    .orderSn(order.getSn())
                    .paymentReceivableNo(order.getReceivableNo())
                    .outOrderNo("AF" + SnowFlake.getIdStr())
                    .refundReason("订单取消")
                    .build();
            payment.refund(refundLog);

    }



}
